/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-04-10     weihui       the first version
 */


#include <Bsp/bsp_uart4_dma.h>

#define SAMPLE_UART_NAME       "uart4"      /* 串口设备名称 */

/* 串口接收消息结构*/
struct rx_msg
{
    rt_device_t dev;
    rt_size_t size;
};
/* 串口设备句柄 */
static rt_device_t serial;
/* 消息队列控制块 */
static struct rt_messagequeue rx_mq;

/* 接收数据回调函数 */
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
    struct rx_msg msg;
    rt_err_t result;
    msg.dev = dev;
    msg.size = size;

    result = rt_mq_send(&rx_mq, &msg, sizeof(msg));
    if ( result == -RT_EFULL)
    {
        /* 消息队列满 */
//        rt_kprintf("message queue full！\n");
    }
    return result;
}

int32_t serial_dma_rx(uint8_t* buff,int32_t wait)
{
    struct rx_msg msg;
    rt_err_t result;
    int32_t rx_length;
    rt_memset(&msg, 0, sizeof(msg));
    /* 从消息队列中读取消息*/
    result = rt_mq_recv(&rx_mq, &msg, sizeof(msg), wait);
    if(result == RT_EOK )
    {
        /* 从串口读取数据*/
        rx_length = rt_device_read(msg.dev, 0, buff, msg.size);
//        for(int i=0;i<msg.size;i++)rt_kprintf("%02x ",buff[i]);
//        rt_kprintf("\n");
    }
    return rx_length;
}


int uart_dma_sample(void)
{
    rt_err_t ret = RT_EOK;
    static char msg_pool[32];


    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;  /* 初始化配置参数 */

    // step1：查找串口设备
    serial = rt_device_find(SAMPLE_UART_NAME);

    if (!serial)
    {
        rt_kprintf("find %s failed!\n", SAMPLE_UART_NAME);
        return RT_ERROR;
    }

    // step2：修改串口配置参数
    config.baud_rate = BAUD_RATE_115200;      //修改波特率为 115200
    config.data_bits = DATA_BITS_8;           //数据位 8
    config.stop_bits = STOP_BITS_1;           //停止位 1
    config.bufsz     = 256;                   //修改缓冲区 buff size 为 128
    config.parity    = PARITY_NONE;           //无奇偶校验位

    // step3：控制串口设备。通过控制接口传入命令控制字，与控制参数
    rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config);

    /* 初始化消息队列 */
    rt_mq_init(&rx_mq, "rx_mq",
               msg_pool,                 /* 存放消息的缓冲区 */
               sizeof(struct rx_msg),    /* 一条消息的最大长度 */
               sizeof(msg_pool),         /* 存放消息的缓冲区大小 */
               RT_IPC_FLAG_FIFO);        /* 如果有多个线程等待，按照先来先得到的方法分配消息 */

    /* 以 DMA 接收及轮询发送方式打开串口设备 */
    rt_device_open(serial, RT_DEVICE_FLAG_DMA_RX);
    /* 设置接收回调函数 */
    rt_device_set_rx_indicate(serial, uart_input);

    return ret;
}
